/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/dao/AbstractStructureSupport.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Id: AbstractStructureSupport.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-02 11:09:12 +0800 (周一, 02 七月 2012) $
 * $Revision: 1034 $
 */
package com.elancom.framework.dao;

import java.util.Map;
import java.util.Map.Entry;

import com.elancom.framework.commons.util.StringUtils;
import com.elancom.framework.dao.enums.MatchMode;
import com.elancom.framework.dao.expression.Condition;

/**
 * @author elancom
 * @date 2012-5-6
 */
@SuppressWarnings("unchecked")
public abstract class AbstractStructureSupport<T extends AbstractStructureSupport<T>> extends ParameterSupport {
	protected transient StringBuilder whereString = new StringBuilder("");

	private boolean whered;

	public AbstractStructureSupport() {
		super();
	}

	public Map<String, Object> getParamMap() {
		return paramMap;
	}

	public T parameter(Map<String, Object> paramMap) {
		if (paramMap != null) {
			for (Entry<String, Object> entry : paramMap.entrySet()) {
				this.paramMap.put(entry.getKey(), entry.getValue());
			}
		}

		return (T) this;
	}

	public T where(Condition condition) {
		if (condition != null) {
			where(condition.toHQLString());
		}

		return (T) this;
	}

	public T notEq(String name, String value) {
		return notEq(name, radomNamed(), value);
	}

	/**
	 * @return
	 */
	private String radomNamed() {
		return StringUtils.random("_", 16);
	}

	public T notEq(String name, String varName, String value) {
		if (StringUtils.isNotBlank(name)) {
			where(name + " != :" + varName).setParameter(varName, value);
		}

		return (T) this;
	}

	public T eq(String name, String value) {
		return eq(name, radomNamed(), value);
	}

	public T eq(String name, String varName, String value) {
		if (StringUtils.isNotBlank(name)) {
			where(name + " = :" + varName).setParameter(varName, value);
		}

		return (T) this;
	}

	public T where(String whereString) {
		if (StringUtils.isNotBlank(whereString)) {
			if (!whered) {
				this.whereString.append(" where ");
				whered = true;
			} else {
				this.whereString.append(" and ");
			}
			this.whereString.append(whereString);
		}

		return (T) this;
	}

	public T whereIn(String name, String inStr) {
		if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(inStr)) {
			where(name + " in (" + inStr + ")");
		}

		return (T) this;
	}

	public T where(String name, Object value) {
		return where(name, radomNamed(), value);
	}

	public T where(String name, String varName, Object value) {
		if (StringUtils.isNotBlank(name)) {
			where(name + " = :" + varName).setParameter(varName, value);
		}

		return (T) this;
	}

	public T like(String name, String varName, Object value) {
		if (StringUtils.isNotBlank(name)) {
			where(name + " like :" + varName).setParameter(varName, value);
		}

		return (T) this;
	}

	public T likeIfNotNull(String name, Object value) {
		return likeIfNotNull(name, value, MatchMode.ANY);
	}

	public T likeIfNotNull(String name, Object value, MatchMode mode) {
		if (StringUtils.isNotBlank(name) && value != null) {
			like(name, name, mode.toMatch(value.toString()));
		}

		return (T) this;
	}

	public T likeIfNotBlank(String name, Object value) {
		return likeIfNotBlank(name, value, MatchMode.ANY);
	}

	public T likeIfNotBlank(String name, Object value, MatchMode mode) {
		if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(value)) {
			like(name, radomNamed(), mode.toMatch(value.toString()));
		}

		return (T) this;
	}

	public T whereIfNotNull(String property, Object propertyValue) {
		if (propertyValue != null) {
			if (StringUtils.isNotBlank(property)) {
				where(property, propertyValue);
			}
		}

		return (T) this;
	}

	public T whereIfNotBlank(String property, Object propertyValue) {
		if (StringUtils.isNotBlank(propertyValue)) {
			if (StringUtils.isNotBlank(property)) {
				where(property, propertyValue);
			}
		}

		return (T) this;
	}

	public T whereIfNotNull(String property, String varName, Object nameParamValue) {
		if (nameParamValue != null) {
			if (StringUtils.isNotBlank(property) && StringUtils.isNotBlank(varName)) {
				where(property, varName, nameParamValue);
			}
		}

		return (T) this;
	}

	public T whereIfNotBlank(String property, String varName, Object paramValue) {
		if (StringUtils.isNotBlank(paramValue)) {
			if (StringUtils.isNotBlank(property) && StringUtils.isNotBlank(varName)) {
				where(property, varName, paramValue);
			}
		}

		return (T) this;
	}

	@Override
	public T setParameter(String key, Object value) {
		super.setParameter(key, value);
		return (T) this;
	}
}
